/////////////////////////////////////////////////////////////////////////////
// Name:        ax_utils.h
// Purpose:     AxTk framework - utilities for archives and more
// Author:      Julian Smart
// Modified by: 
// Created:     2009-02-27
// RCS-ID:      
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#ifndef _AX_UTILS_H_
#define _AX_UTILS_H_

/*
 * Includes
 */

#include "wx/dir.h"
#include "wx/filename.h"

/*
 * Styles and types
 */

enum
{
	// overwrite the destination file if it exists
	AX_COPYFILE_OVERWRITE = 1,

	// don't fail if the permissions of the destination file can't be
	// set (after successful copy)
	AX_COPYFILE_IGNORE_PERMISSIONS = 2
};

/*
 * Forward declarations
 */

class wxInputStream;
class wxOutputStream;
class wxFileHistory;
class wxFileOutputStream;
class wxConfigBase;
class wxZipEntry;
class wxZipInputStream;
class wxProgressDialog;

/**
    @class AxFileUtilities
    
    Miscellaneous file functions.

    @category{ax}
 */

class AxFileUtilities
{    
public:
    /// Constructor.
    AxFileUtilities() {}

    /// Get a suitable directory for putting documents by default.
    static wxString GetDocumentDirectory();

    /// Get the application data directory for the current user.
    static wxString GetUserAppDataDirectory(const wxString& appName);

    /// Append paths without duplicating the separator.
    static wxString AppendPaths(const wxString& p1, const wxString& p2, const wxString& sep = wxFILE_SEP_PATH);
    
    /// Make sure the folder exists, otherwise create recursively.
    static bool MkDirRecursively(const wxString& path);

    /// Remove dir recursively.
    static bool RemoveDirRecursively(const wxString& path);

    /// Change the Unix file mode.
    static bool Chmod(const wxString& path, int mode, bool addMode = false);

    /// Get the Unix file mode. If path is empty, get the default mode for a new file.
    static int GetFileMode(const wxString& path);

    /// Find the given file under the a path and change its mode.
    static bool FindAndChmod(const wxString& searchPath, const wxString& filename, int mode, bool addMode = false);

    /// Copy files in sourceDir to destDir.
    static bool CopyDir(const wxString& sourceDir, const wxString& destDir, bool ifNotExists = true, const wxString& wildcard = wxT("*"), int dirFlags = wxDIR_FILES);

    /// Replacement for wxWidgets function that fails if can't set permissions.
    static bool CopyFile(const wxString& file1, const wxString& file2, int flags = AX_COPYFILE_OVERWRITE | AX_COPYFILE_IGNORE_PERMISSIONS);

    /// Copy a fixed size of data from an input stream to an output stream,
    /// using a buffer to speed it up.
    static bool BufferedCopy(wxInputStream& inStream, wxOutputStream& outStream, size_t size);
    
    /// Copy data from an input stream to an output stream, using a buffer to speed it up.
    /// This version doesn't need a size.
    static bool BufferedCopy(wxInputStream& inStream, wxOutputStream& outStream);
    
    /// Copy file to stream.
    static bool CopyFileToStream(wxOutputStream& stream, const wxString& filename);
    
    /// Copy stream to new file.
    static bool CopyStreamToFile(wxInputStream& stream, const wxString& filename, size_t size);

    /// Gets the extension.
    static wxString GetExtension(const wxString& filename);

    /// Does the filename have this extension?
    static bool HasExtension(const wxString& filename, const wxString& ext);

    /// Intelligent strip extension: don't strip before a separator,
    /// and don't strip if the 'extension' is different from the passed extension
    /// that we expect - can be comma-separated list.
    static bool StripExtension(wxString& path, const wxString& validExtensions = wxEmptyString);

    /// Ensure extension is present.
    static void EnsureExtension(wxString& path, const wxString& requiredExt);

    /// Improved wxFileName::SplitPath.
    static bool SplitPath(const wxString& fullpath,
                          wxString *path,
                          wxString *name,
                          wxString *ext,
                          wxPathFormat format = wxPATH_NATIVE);

    /// Remove trailing separator.
    static bool RemoveTrailingSeparator(wxString& filename);

    /// Execute the command.
    static bool ExecuteFile(const wxString& command, const wxString& specificErrorMessage = wxEmptyString);

    /// Convert to a valid filename (assumes no path separators in filename)
    static wxString MakeValidFilename(const wxString& filename, bool allowSpaces = true);

};

/**
    @class AxArchiveUtilities
    
    Miscellaneous archive functions.

    @category{ax}
 */

class AxArchiveUtilities
{    
public:
    AxArchiveUtilities() {}

    /// Get the zip entry for the given filename
    static wxZipEntry* FindEntry(wxZipInputStream& stream, const wxString& filename);

    /// Copy a fixed size of data from an input stream to an output stream,
    /// using a buffer to speed it up.
    static bool BufferedCopy(wxInputStream& inStream, wxOutputStream& outStream, size_t size);

    /// Copy stream to new file
    static bool CopyStreamToFile(wxInputStream& stream, const wxString& filename, size_t size);

    /// Copy entry to new file
    static bool CopyEntryToFile(wxZipInputStream& stream, const wxString& filename, wxZipEntry* entry);

    /// Unarchive to the given folder, optionally notifying the progress dialog
    static bool UnzipTo(const wxString& archive, const wxString& destinationFolder, wxProgressDialog* progressDialog = NULL);

    /// Unarchive to the given file
    static bool GUnzipTo(const wxString& archive, const wxString& destinationFile);

    /// Unarchive to the given folder, optionally notifying the progress dialog
    static bool UntarTo(const wxString& archive, const wxString& destinationFolder, wxProgressDialog* progressDialog = NULL);

    /// Copy to the given folder, optionally notifying the progress dialog.
    /// relativeTo is the folder to be substracted from each file to determine the relative path for the destination file.
    static bool CopyTo(const wxString& relativeTo, const wxArrayString& files, const wxString& destinationFolder, wxProgressDialog* progressDialog = NULL);

    /// Get the number of entries in the zip file
    static int GetZipEntryCount(const wxString& filename);

};

/**
    @class AxUIUtilities
    
    Miscellaneous user interface functions.

    @category{ax}
 */

class wxOutputStream;
class wxInputStream;
class wxDataOutputStream;
class wxDataInputStream;

class AxUIUtilities
{    
public:
    AxUIUtilities() {}

    /// Get a reasonable themed border style
    static wxBorder GetSuitableThemedBorderStyle();

    /// Choose a folder
    static void ChooseFolder(wxTextCtrl* textCtrl, wxWindow* win);

    /// Choose a file
    static void ChooseFile(wxTextCtrl* textCtrl, const wxString& wildcard, const wxString& ext, wxWindow* win);

    /// Find a child window by class
    static wxWindow* FindWindowByClass(wxWindow* parent, wxClassInfo* info);

    /// Gets a child window under the given point
    static wxWindow* ChildWindowFromPoint(wxWindow* win, const wxPoint& pt, bool hidden = true, int depth = -1);
    static wxWindow* ChildWindowFromPoint(const wxPoint& pt, bool hidden = true, int depth = -1);
};

/// Calculate a suitable scale for an image to fit into the given space
wxSize AxCalculateScaledImageSize(const wxSize& maxSize, const wxSize& imageSize);

/// Remove bad characters from a filename
bool AxRemoveNonFilenameCharacters(wxString& str);

/// Gets suitable text for a given keycode
wxString AxGetSpeakableTextForKeyCode(int keycode);

#endif
    // _AX_UTILS_H_
